﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;

namespace calendar
{
/// <summary>
/// 日历类
/// </summary>
class Calendar
{
    private int m_uid;
    private string m_name;
    private ArrayList m_weekDays;
    private ArrayList m_exceptions;

    public Calendar()
    {
        m_uid = 1;
        m_name = "Standard";
        m_weekDays = Calendar.GetDefaultWeekDays();
        m_exceptions = new ArrayList();
    }

    public int UID
    {
        get {
            return m_uid;
        } set {
            m_uid = value;
        }
    }

    public string Name
    {
        get {
            return m_name;
        } set {
            m_name = value;
        }
    }

    public CalendarException AddException(CalendarException exp)
    {
        if (exp != null) {
            m_exceptions.Add(exp);
            return exp;
        } else {
            return null;
        }
    }

    private CalendarException AddException()
    {
        CalendarException exp = new CalendarException();
        m_exceptions.Add(exp);
        return exp;
    }

    public static ArrayList GetDefaultWeekDays()
    {
        ArrayList m_weekDays = new ArrayList();

        WeekDay Sunday = new WeekDay(1, 0);
        WeekDay Monday = new WeekDay(2, 1);
        WeekDay Tuesday = new WeekDay(3, 1);
        WeekDay Wednesday = new WeekDay(4, 1);
        WeekDay Thursday = new WeekDay(5, 1);
        WeekDay Friday = new WeekDay(6, 1);
        WeekDay Saturday = new WeekDay(7, 0);

        Sunday.TimePeriod = null;


        Monday.TimePeriod = null;
        Monday.WorkingTimes.Add(new DateRange(DateTime.Parse("0001-01-01T08:00:00"), DateTime.Parse("0001-01-01T12:00:00")));
        Monday.WorkingTimes.Add(new DateRange(DateTime.Parse("0001-01-01T13:00:00"), DateTime.Parse("0001-01-01T17:00:00")));


        Tuesday.TimePeriod = null;
        Tuesday.WorkingTimes.Add(new DateRange(DateTime.Parse("0001-01-01T08:00:00"), DateTime.Parse("0001-01-01T12:00:00")));
        Tuesday.WorkingTimes.Add(new DateRange(DateTime.Parse("0001-01-01T13:00:00"), DateTime.Parse("0001-01-01T17:00:00")));

        Wednesday.TimePeriod = null;
        Wednesday.WorkingTimes.Add(new DateRange(DateTime.Parse("0001-01-01T08:00:00"), DateTime.Parse("0001-01-01T12:00:00")));
        Wednesday.WorkingTimes.Add(new DateRange(DateTime.Parse("0001-01-01T13:00:00"), DateTime.Parse("0001-01-01T17:00:00")));

        Thursday.TimePeriod = null;
        Thursday.WorkingTimes.Add(new DateRange(DateTime.Parse("0001-01-01T08:00:00"), DateTime.Parse("0001-01-01T12:00:00")));
        Thursday.WorkingTimes.Add(new DateRange(DateTime.Parse("0001-01-01T13:00:00"), DateTime.Parse("0001-01-01T17:00:00")));

        Friday.TimePeriod = null;
        Friday.WorkingTimes.Add(new DateRange(DateTime.Parse("0001-01-01T08:00:00"), DateTime.Parse("0001-01-01T12:00:00")));
        Friday.WorkingTimes.Add(new DateRange(DateTime.Parse("0001-01-01T13:00:00"), DateTime.Parse("0001-01-01T17:00:00")));

        Saturday.TimePeriod = null;

        m_weekDays.Add(Sunday);
        m_weekDays.Add(Monday);
        m_weekDays.Add(Tuesday);
        m_weekDays.Add(Wednesday);
        m_weekDays.Add(Thursday);
        m_weekDays.Add(Friday);
        m_weekDays.Add(Saturday);

        return m_weekDays;
    }

    public long GetDuration(DateTime startDate, DateTime finishDate)
    {
        long dur = 0;
        if (startDate >= finishDate) {
            return dur;
        }
        //dur = finishDate.Ticks - startDate.Ticks;
        //double tm = util.Ticks2Hour(dur);

        DateTime it = new DateTime(startDate.Ticks);
        //long start = startDate.Ticks;

        while (it <= finishDate) {
            CalendarException exp = this.GetExcption(it);
            //long inDayTicks = it.TimeOfDay.Ticks;
            //if ((inDayTicks == 0) && (it.AddDays(1) <= finishDate)) {
            //    inDayTicks = TimeSpan.Parse("23:59:59").Ticks;
            //} else if ((inDayTicks == 0) && (it.AddDays(1) > finishDate)) {
            //    inDayTicks = finishDate.TimeOfDay.Ticks;
            //}

            if (exp != null) {
                //如果有例外日期
                if (IsWorkingDay(it)) {
                    foreach (DateRange dr in exp.WorkingTimes) {
                        ////////////////////////////////////////////////
                        long res = dr.InRangeOfTicks(it, finishDate);
                        if (res != 0) {
                            dur += res;
                        } else {
                            break;
                        }
                    }
                }
            } else {
                //没有例外
                if (IsWorkingDay(it)) {
                    //是工作日
                    WeekDay weekday = GetWeekDay(it.DayOfWeek);

                    foreach (DateRange dr in weekday.WorkingTimes) {
                        ////////////////////////////////////////////////

                        long res = dr.InRangeOfTicks(it, finishDate);
                        if (res != 0) {
                            dur += res;
                        } else {
                            break;
                        }
                    }
                }
            }
            it = it.AddDays(1).Date;
        }
        return dur;
    }

    //从结束日期 和 持续时间 推出开始日期
    public DateTime GetStartDate(DateTime finishDate, long dur)
    {
        DateTime start = finishDate;

        while (dur > 0) {
            CalendarException exp = this.GetExcption(start);
            if (exp != null) { //当日有例外
                if (IsWorkingDay(start)) { //当日是工作日
                    foreach (DateRange dr in exp.WorkingTimes) {
                        long res = dr.InRangeOfTicks(start.Ticks);
                        dur = dur - res;
                    }
                } else { // 当日非工作日
                    continue;
                }
            }

        }
        return start;
    }

    private WeekDay GetWeekDay(DayOfWeek day)
    {
        return (WeekDay)m_weekDays[(int)day];
    }

    private bool IsWorkingDay(DateTime date)
    {

        foreach (CalendarException exp in m_exceptions) {
            if (exp.DayWorking == 1) {
                if (exp.ContiainsDate(date)) {
                    return true;
                }
            } else {
                if (exp.ContiainsDate(date)) {
                    return false;
                }
            }
        }
        if (((WeekDay)m_weekDays[date.DayOfWeek.GetHashCode()]).DayWorking == 1)
            return true;
        else
            return false;
    }

    private CalendarException GetExcption(DateTime date)
    {
        foreach (CalendarException exp in m_exceptions) {
            if (exp.ContiainsDate(date)) {
                return exp;
            }
        }
        return null;
    }

    //合并weekday 与 exp中的workingTime
    private ArrayList MergeWorkingTime(ArrayList exp_wkt, ArrayList wdy_wkt, int day_working)
    {
        //如果例外是 工作例外( day_working == 1), 且 weekday 当天无工作时间段, 单 exp_wkt 合并处理.
        if (day_working == 1) {

        } else {

        }

        return null;
    }
}
}
